home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 2
/
Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso
/
Aminet
/
gfx
/
opal
/
OVLine11.lzh
/
ovlines.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-02-22
|
16KB
|
444 lines
/* OVLINES.C Version 1.1
A Line drawing toy similar to PolyScope but for the OpalVision
INTRO:
This hack draws lines in symmetry on the OpalVision screen. It appears
no purpose, but is good eyecandy. An alternative use would be a screen
blanker. This hack is in its infancy, and in response to
requests for this sort of drawing program. It is based loosly on a program
called IToy in AMiga Basic ( about 1986), and is written in c compiled by
SAS brand C compiler Version 6.02.
USE:
To use, type "ovlines" at the CLI prompt. I did not bother to
make an Icon for it yet. MAKE SURE FIRST THAT YOUR SCREENMODE IS EITHER
NTSC OR PAL. If it is set to 800x600 or VGA results are unpredictible.
To exit, press and hold the mouse button.
A few options are added. Typing "ovlines l" will latch the display
and leave the screen as of when exit was chosen as a backdrop to workbench.
Typing "ovlines s filename" will save the screen as an IFF24 file with that
name. If you want it in another directory, specify the complete absolute
path. I did not use JPEG since its optimized for full 24 bits and is not
efficient here, and the degradation is more apparent with this type of
picture, plus it takes significantly longer. Even the IFF save uses all
24 bits, the pictures are actually larger than the screen! is better than
nothing.
THEORY:
Ovlines opens an 8 bit plane screen in Hires Overscan. It then algorith
matically generates a pallette (see PalGrad() ) that creates an array of colors
by stepping through them with different slopes. I had tried totally random
palettes and a single gradient and this method seemed more pleasing than
either.
The end points of the lines(x1,y1,x2,y2) are stepped by the interval
x1i,x2i, etc. Four lines are created to connect to four points on the
screen. The end points are clipped when they would get outside the screen
and the direction is reversed. Each group is drawn with the next color
out of 256. Color 0 is not used or affected, and that is the black back-
ground. When all 255 colors are printed, new endpoints and intervals are
selected, and a different design is printed. Every fourth run, the screen is
cleared, as it becomes too cluttered after that to make out any detail.
LEGAL AND PURPOSE:
This source is copyright 1993 Jim Boros, and may be redistibuted
by any means as long as this notice is intact. Distribution is encouraged
by Fred Fish and the OpalVision BBS, and BIX. It may be used in whole or
part for any noncommercial software product, especially a screen blanker.
You may alter it and redistribute
it, this is mainly for educational purposes, and it is hoped other program-
mers will add to it and repost. If you alter this, please acknowledge
the origin plus any other programmers that contributed to it by leaving
these notices intact(you may add your credits for your additions and
modifications). Use this at your own risk, I will not be responsible for
any crashed machines or for any lost productivity or other damages caused
by this product(there shouldn't be any, but must cover my a**).
OpalVision is a trademark of Opal Party Ltd.
Amiga is a trademark of Commodore- Amiga, Inc.
Bars & Pipes is a trademark of Blue Ribbon Soundworks.
This is distributed in request for these hacks, and this is to fill that
and to educate others on OpalVision programming. It is hoped others use
this code this way, and add their own tricks and share these with other
OpalVision programmers. Also, it is a piece of Eye Candy for Valentines
day and Easter.
No set fee is requested for use of the program, however donations are
cheerfully accepted at the address below. Future versions may be shareware
or part of a commercial package, but will be quite economical.
MY QUESTION:
I have tried to write programs with AMiga over Opal using DualDisplay
and AmigaPriority(). Every time it updated the Amiga overlay would flash.
Anyone have a workaround?
FUTURE PLANS:
If however, you wish to see a feature added and are not a programmer
or if you are and have a question or comment about this, leave mail to me
(JimB) on OpalVIsion BBS or jboros on BIX, or write to Borotec below.
I will write an AGA version of this as soon as I get an AMiga
4000 or better computer. If you can't wait for that, just donate one
and I'll write it and send you a disk of it. Also, look for more
OpalVision programs, Modules for Bars&Pipes(Blue Ribbon Soundworks)
are being considered. An algorithmic music composition program, MIDI Math,
is available from Borotec Inc, Box 17149, Euclid, Ohio 44117 for $29
PPD. This turns mathmatical equations into music compositions. A version
to run with Bars & Pipes is under development, and it has not been determined
whether Borotec or Blue Ribbon will market.
V1.10 J. Boros 2-13-93 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>
#include <stddef.h>
#include <math.h>
#include <time.h>
#include <opal/opallib.h>
#include <graphics/gfxbase.h>
#include <exec/memory.h>
#include <hardware/custom.h>
#include <proto/all.h>
unsigned char *setpal(double hue, double sat,double lite, unsigned char *res);
double mag_blue(double), mag_green(double),mag_red(double);
double ITENO=255.0 ; /* 8 bit pallette instead of 6 per color */
void Clean_Up(char *,UBYTE); /* my prototypes go here */
void RandPal(void),CycleColors(void);
void PalGrad(short,short,short),PalSmooth(short,short);
#define MAXCOLORS 256
#define DISP_W 732 /* overscan screen */
#define DISP_H 476 /* overscan height */
#define TRUE 1
#define FALSE 0
#define BAD 0
#define OK 1
#define RBMASK 0x0400
#define MAXMODE 2 /* increase as more modes are added */
#define colour color ; for programmers outside the USA
#define Colour Color
int clk[2]; /* for reading time */
struct OpalBase *OpalBase = NULL;
struct OpalScreen *OScrn;
/* Joystick and Mouse primitive stuff.
Yes, I bang the hardware but this is not for video, and is read only */
__far extern struct Custom custom; /* for registers */
__far UBYTE *Button = (UBYTE *)0xbfe001; /* Nasty */
__far UWORD *RButton= (UWORD *)0xdff016; /* read right button */
/* bit 10, use dff016 for right */
#define RIGHT custom.joy1dat & 2
#define LEFT custom.joy1dat & 0x200
#define UP ( custom.joy1dat & 1 )
#define DOWN ( custom.joy1dat & 0x100)
#define FIRE (*Button & 0x80)
main(argc,argv)
int argc;
char **argv;
{
long scm;
short mode,i,x1,y1=323,x2,y2=77;
short x1i,y1i,x2i,y2i; /* drawing variables */
UBYTE c=1,ci,inch,argf,pm=1;
i=0;
mode=0; /* default to lines */
argf=1; /* normal */
timer(clk); /* get time */
srand(clk[0]+clk[1]); /*reseed randomizer */
printf("OVlines V1.10 Copyright J. Boros 1993 \n");
printf("Usage: ovlines [pm] [option] [filename] \n");
printf("Where pm =0 for random, 1 for ramped, 2 for smooth hues \n");
printf("Hold Right Mouse Button a few sec to change Mode \n");
x1i=x2i=y1i=y2i=9; /* default increment */
OpalBase = (struct OpalBase *) OpenLibrary ("opal.library",0L);
if (OpalBase==0L)
Clean_Up ("Can't open opal.library\n",10);
OScrn = NULL;
scm = ILACE24 | HIRES24 | OVERSCAN24 | PALMAP24 | PLANES8 ;
OScrn = OpenScreen24(scm) ; /* open an OpalVision Screen */
if ( !OScrn) Clean_Up( "Cannot open OV Screen ",22);
StopUpdate24();
AutoSync24(FALSE);
OVPriority();
ci = (UBYTE) *argv[1];
if ( (argc >=1 ) && isdigit(ci) ){
pm= ci-48; /* if a number entered use */
argf=2; } /* look one higher for argument */
switch (pm) {/* decide what to do with palette */
case 0: RandPal(); break; /* have utterly random palette */
case 1: PalGrad(13,5,47); /* psuedo randomize palette */ break;
case 2 : PalSmooth(98,60); /* create smooth palette */ break;
}
UpdatePalette24();
RegWait24();
/* memcpy(&OpalScreen->Palette[0],&Colours[0][0],768); */
while (*Button &0x040) { /* try and cycle colours until button pressed */
c++;
if (((c&127)==0) || ( !FIRE && !(c&3)) ) { /* after each 256 line sets change pattern */
c=1; /* don't draw bkg color */
x1= rand() % DISP_W;
x2=rand() %DISP_W;
timer(clk); /* get time */
srand(clk[0]+clk[1]); /*reseed randomizer */
y1=rand() % DISP_H;
y2=rand()% DISP_H; /* randimize */
x1i=x2i=rand() &0x0F | 1;
y1i=y2i=rand() &0x07 | 1;
/* maybe I'll rand the intervals */
i++;
/* inch=getch(); */
if ( !(i&7) ) {ClearQuick24(); /* clear screen every 8th run */
UpdatePalette24(); i=0;
}
}
x1+=x1i; y1+=y1i;
x2-=x2i; y2-=y2i; /* add the increments */
if ( UP ) { y1+=10; y2 += 10; }/* Steer it W Joystick JB 2-16 */
if ( DOWN ) { y1-=10; y2 -=10; }
if ( LEFT ) { x1-= 14; x2-=14; }
if ( RIGHT) { x1+=14; x2+= 14; }
/* clip values, keep them on screen */
if (x1 <0) { x1 =0; x1i =x1i *(-1); }
if (x1 >DISP_W) { x1 =DISP_W-x1i; x1i =x1i *(-1); }
if (y1 <0) { y1 =0; y1i =y1i *(-1); }
if (y1 >DISP_H) { y1 =DISP_H-y1i; y1i =y1i *(-1); }
if (x2 <0) { x2 =0; x2i =x2i *(-1); }
if (x2 >DISP_W) { x2 =DISP_W-x2i; x2i =x2i *(-1); }
if (y2 <0) { y2 =0; y2i =y2i *(-1); }
if (y2 >DISP_H) { y2 =DISP_H-y2i; y2i =y2i *(-1); }
OScrn->Pen_R=256-c; /* set colour to draw NOTE WE ONLY NEED USE RED!*/
/* now draw them */
CycleColors();
switch ( mode) { /* decide several shapes */
case 0 :
DrawLine24(OScrn,x1,y1,x2,y2);
DrawLine24(OScrn,x1,DISP_H-y1,x2,DISP_H-y2);
DrawLine24(OScrn,DISP_W-x1,y1,DISP_W-x2,y2);
DrawLine24(OScrn,DISP_W-x1,DISP_H-y1,DISP_W-x2,DISP_H-y2);
break;
case 1 : /* try boxes */
RectFill24(OScrn,min(x1,x2),min(y1,y2),max(x1,x2),max(y1,y2));
if ( c <255) OScrn->Pen_R++; /* try incr pens */
/* RectFill24(OScrn,DISP_W-max(x1,x2),DISP_H-max(y1,y2),
DISP_W-min(x1,x2),DISP_H-min(y1,y2) ); */
break;
case 2 : /* ellipses? */
DrawEllipse24(OScrn, (x1+x2)/2,(y1+y2)/2, abs(x1-x2)/2,abs(y1-y2)/2);
DrawEllipse24(OScrn,DISP_W-((x1+x2)/2),DISP_H-((y1+y2)/2), abs(x1-x2)/2,abs(y1-y2)/2);
break;
}
if ((!(*RButton & RBMASK)) && (!(c &3))) { /* debounsed rmb in*/
mode++;
if (mode >MAXMODE) mode=0; /* limit if gets too high */
}
WaitTOF();
Refresh24(); /* update screen and give OS a breather for any tasks */
Delay(1);
} /* end of draw loop */
if ( argc > argf) { /* we typed some extra stuff! */
switch ((UBYTE) *argv[argf] ) { /* if we typed a command use disp as bakdrop*/
case 'l' : /* latch display and use as backdrop */
AmigaPriority ();
DualDisplay24 ();
AutoSync24 (FALSE); /* try turn off autosync */
Delay (1);
LatchDisplay24 (TRUE);
break;
case 's' : /* save as IFF file using name */
if(argc>(argf+1))
x1=SaveIFF24(OScrn,argv[argf+1],NULL,NULL); /* save as iff24 */
Clean_Up("Attemped to save IFF",x1);
}
}
Clean_Up(" Normal Exit",0);
}
void RandPal()
{
int i,j; /* fill palette with RANDOM or pseudorandom colours */
for(i=3; i<(MAXCOLORS*3); i++){
j=rand();
OScrn->Palette[i]= (UBYTE) ((j>>3) & 0x0FF); /* try LSB's */
}
}
void PalGrad(rm,gm,bm)
short rm,gm,bm;
{ /* gradients depending on values entered as 'mod' values for ea colour */
int i;
for(i=1;i< MAXCOLORS; i++){
OScrn->Palette[i*3] =(i*rm) &0x0ff+200 ;
OScrn->Palette[i*3+1] =(i*gm) &0x0ff ;
OScrn->Palette[i*3+2] =(i*bm) &0x0ff ; /* appear to cycle */
}
}
void PalSmooth(short s,short v)
{
int i;
for(i=1; i<MAXCOLORS; i++)
setpal((double)i/256.0,s/100.0,v/100.0,&OScrn->Palette[i*3]);
/* make a very smooth transition of hue, with high saturation */
}
void CycleColors() {
UBYTE rl,gl,bl;
/* cycle colors, plays 'musical' registers. Screen structure is
global, as one slip here invites Mr. GURU
WE DO NOT CYCLE COLOR 0, it is the black background */
rl=OScrn->Palette[765]; /* get old top values R*/
gl=OScrn->Palette[766]; /* get old top values G*/
bl=OScrn->Palette[767]; /* get old top values B*/
memmove(&OScrn->Palette[6],&OScrn->Palette[3],762);
OScrn->Palette[3]=rl; /* leave color 0 alone! */
OScrn->Palette[4]=gl;
OScrn->Palette[5]=bl;
UpdatePalette24(); /* make it regiter on OV */
}
void Clean_Up(error,ExitVal)
UBYTE ExitVal;
char *error;
{
if (OpalBase) {
AmigaPriority();
/* SingleDisplay24(); */
if (OScrn) {
CloseScreen24();
OScrn = NULL;
}
CloseLibrary((struct Library *)OpalBase);
OpalBase = NULL;
}
printf(" %s \n",error); /* tell why we quit! */
exit(ExitVal);
}
/* conversion from HSV to RGB */
/* derived from Computer Applications Journal Oct/Nov 92 */
/* call setpal below to use, other routines here are subparts of setpal
hue,sat,lite are double floating point between 0 and 1.
res is a pointer to the red entry in the palette */
unsigned char *setpal(double hue, double sat,double lite, unsigned char *res)
{
double red,green,blue;
double red1,gren1,blu1,euh,sat0;
if (hue <= 0.5) euh=hue+0.5; /* hue compliment */
else euh=hue-0.5;
sat0=2.0*lite+min((-4.0*lite) + 2.0, 0.0);
sat0=max(sat0,0.0); /* max sat= f(lite) */
sat0=min(sat0,1.0);
blue=mag_blue(hue);
blue=max(blue,0.0);
blue=min(blue,1.0);
blu1=mag_blue(euh);
blu1=max(blu1,0.0);
blu1=min(blu1,1.0);
blue= ITENO * lite *(blue + ( 1.0 - sat*sat0) *blu1);
green=mag_green(hue);
green=max(green,0.0);
green=min(green,1.0);
gren1=mag_green(euh);
gren1=max(gren1,0.0);
gren1=min(gren1,1.0);
green= ITENO * lite *(green + ( 1.0 - sat*sat0) *gren1);
red=mag_red(hue);
red=max(red,0.0);
red=min(red,1.0);
red1=mag_red(euh);
red1=max(red1,0.0);
red1=min(red1,1.0);
red= ITENO * lite *(red + ( 1.0 - sat*sat0) *red1);
*res= (unsigned char) red; /* stash results in BYTE buffer */
*(res+1) =(unsigned char) green;
*(res+2) =(unsigned char) blue;
return(res);
}
double mag_red(double x) /* switch red and blue for OpalVision Compat */
{
double result;
result=(max(0.3333-x,0.0)+min(x-0.16667,0.0)+max(x-0.6667,0.0)+
min(0.8333-x,0.0))/0.1666;
return(result);
}
double mag_green(double x)
{
double result;
result=( x+min(0.1667-x,0.0)+min(0.5-x,0.0)+max(x-0.6667,0.0))/0.1667;
return(result);
}
double mag_blue(double x)
{
double result;
result=(max(x-0.3333,0.0)+min(0.5-x,0.0)+min(0.8333-x,0.0))/0.1667;
return(result);
}